<!DOCTYPE html>
<html>
<head>
<title>Fig. 7.1 Graph</title>
<style>
  body {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    margin: 0;
    background-color: #f0f0f0;
  }
  canvas {
    border: 1px solid #999;
    background-color: white;
  }
</style>
</head>
<body>
<canvas id="myCanvas" width="680" height="580"></canvas>
<script>
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');

// --- Configuration ---
const marginLeft = 70;
const marginRight = 30;
const marginTop = 30;
const marginBottom = 60;

const plotWidth = canvas.width - marginLeft - marginRight;
const plotHeight = canvas.height - marginTop - marginBottom;

const tMin = 0;
const tMax = 30;
const rMin = 1.0;
const rMax = 3.5;

// --- Coordinate transformation functions ---
function x(t) {
  return marginLeft + ((t - tMin) / (tMax - tMin)) * plotWidth;
}

function y(R) {
  return marginTop + plotHeight - ((R - rMin) / (rMax - rMin)) * plotHeight;
}

// --- Drawing functions ---

function drawGrid() {
  // Minor grid lines
  ctx.strokeStyle = '#d3d3d3'; // Light grey
  ctx.lineWidth = 0.5;

  // Minor vertical lines (every 0.5 units)
  for (let t = tMin; t <= tMax; t += 0.5) {
      ctx.beginPath();
      ctx.moveTo(x(t), y(rMin));
      ctx.lineTo(x(t), y(rMax));
      ctx.stroke();
  }

  // Minor horizontal lines (every 0.05 units)
  // Use toFixed to avoid floating point precision issues in the loop
  for (let r = rMin; r <= rMax; r = parseFloat((r + 0.05).toFixed(2))) {
      ctx.beginPath();
      ctx.moveTo(x(tMin), y(r));
      ctx.lineTo(x(tMax), y(r));
      ctx.stroke();
  }
  
  // Major grid lines
  ctx.strokeStyle = 'black';
  ctx.lineWidth = 1;

  // Major vertical lines (every 5 units)
  for (let t = tMin; t <= tMax; t += 5) {
    ctx.beginPath();
    ctx.moveTo(x(t), y(rMin));
    ctx.lineTo(x(t), y(rMax));
    ctx.stroke();
  }

  // Major horizontal lines (every 0.5 units)
  for (let r = rMin; r <= rMax; r += 0.5) {
    ctx.beginPath();
    ctx.moveTo(x(tMin), y(r));
    ctx.lineTo(x(tMax), y(r));
    ctx.stroke();
  }
}

function drawLabels() {
    ctx.fillStyle = 'black';
    ctx.font = '16px sans-serif';

    // X-axis labels
    ctx.textAlign = 'center';
    ctx.textBaseline = 'top';
    for (let t = tMin; t <= tMax; t += 5) {
        ctx.fillText(t, x(t), y(rMin) + 8);
    }
    // X-axis title
    ctx.fillText('t / \u00B0C', x(tMin + (tMax - tMin) / 2), y(rMin) + 35);

    // Y-axis labels
    ctx.textAlign = 'right';
    ctx.textBaseline = 'middle';
    for (let r = rMin; r <= rMax; r += 0.5) {
        ctx.fillText(r.toFixed(1), x(tMin) - 8, y(r));
    }
    
    // Y-axis title
    ctx.save();
    ctx.translate(marginLeft - 50, marginTop + plotHeight / 2);
    ctx.rotate(-Math.PI / 2);
    ctx.textAlign = 'center';
    ctx.textBaseline = 'bottom';
    ctx.fillText('R / k\u03A9', 0, 0);
    ctx.restore();
}

function drawCurve() {
    const points = [
        [2.5, 3.50], [5, 3.15], [7.5, 2.85], [10, 2.60], [12.5, 2.35],
        [15, 2.10], [17.5, 1.90], [20, 1.75], [22.5, 1.60], [25, 1.45],
        [27.5, 1.30], [30, 1.20]
    ];

    ctx.strokeStyle = 'black';
    ctx.lineWidth = 2;
    ctx.beginPath();
    ctx.moveTo(x(points[0][0]), y(points[0][1]));

    for (let i = 1; i < points.length; i++) {
        ctx.lineTo(x(points[i][0]), y(points[i][1]));
    }
    ctx.stroke();
}

function drawCaption() {
    ctx.fillStyle = 'black';
    ctx.font = 'bold 16px sans-serif';
    ctx.textAlign = 'center';
    ctx.fillText('Fig. 7.1', canvas.width / 2, canvas.height - 20);
}


// --- Main drawing sequence ---
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, canvas.width, canvas.height);

drawGrid();
drawLabels();
drawCurve();
drawCaption();
</script>
</body>
</html>